/************************************************************************
 * <br>
 * <ul>
 * <li>版权所有：唐山弘川科技有限公司 2009－2020</li>
 * <li>创建日期：2009-8-10</li>
 * <li>初始作者：刘川</li>
 * </ul>
 * <ul>
 * <b>修订历史</b>
 * <li>1、</li>
 * </ul>
 ***********************************************************************/
package com.hy.enterprise.framework.persistence.domain.query.internal ;

import java.util.Date;

import com.hy.enterprise.framework.lang.WeakIdentityHashMap;
import com.hy.enterprise.framework.persistence.domain.query.ISubQuery;
import com.hy.enterprise.framework.persistence.domain.query.internal.managedobjects.AliasedAbstractSchemaName;
import com.hy.enterprise.framework.persistence.domain.query.internal.managedobjects.AliasedAssociationPath;
import com.hy.enterprise.framework.persistence.domain.query.internal.managedobjects.AliasedInCollection;
import com.hy.enterprise.framework.persistence.domain.query.internal.managedobjects.AssociationPath;
import com.hy.enterprise.framework.persistence.domain.query.internal.managedobjects.CollectionAssociationPath;
import com.hy.enterprise.framework.persistence.domain.query.internal.managedobjects.LibraManagedObject;

/**
 * <ul>
 * <li>设计作者：刘川</li>
 * <li>设计日期：2009-8-10</li>
 * <li>设计时间：下午02:16:15</li>
 * <li>设计目的：</li>
 * </ul>
 * <ul>
 * <b>修订历史</b>
 * <li>1、</li>
 * </ul>
 */
public class AliasFactory
{
	/**
	 * 
	 */
	private final static ThreadLocal < WeakIdentityHashMap < Object , LibraManagedObject >>	bindings	=
	                                                                                                      new ThreadLocal < WeakIdentityHashMap < Object , LibraManagedObject >> ( )
	                                                                                                      {
		                                                                                                      @ Override
		                                                                                                      protected WeakIdentityHashMap < Object , LibraManagedObject > initialValue ( )
		                                                                                                      {
			                                                                                                      return new WeakIdentityHashMap < Object , LibraManagedObject > ( ) ;
		                                                                                                      }
	                                                                                                      } ;

	/**
	 * <ul>
	 * <li>设计作者：刘川</li>
	 * <li>设计日期：2009-8-10</li>
	 * <li>设计时间：下午05:42:19</li>
	 * <li>设计目的：</li>
	 * </ul>
	 * <ul>
	 * <b>修订历史</b>
	 * <li>1、</li>
	 * </ul>
	 * 
	 * @return
	 */
	private static WeakIdentityHashMap < Object , LibraManagedObject > bindings ( )
	{
		return AliasFactory.bindings
		                            .get ( ) ;
	}

	/**
	 * <ul>
	 * <li>设计作者：刘川</li>
	 * <li>设计日期：2009-8-10</li>
	 * <li>设计时间：下午02:51:33</li>
	 * <li>设计目的：</li>
	 * </ul>
	 * <ul>
	 * <b>修订历史</b>
	 * <li>1、</li>
	 * </ul>
	 * 
	 * @param what
	 * @return
	 */
	private static String escape (
	                               String what )
	{
		return "'"
		       + what
		             .replaceAll (
		                           "'" ,
		                           "''" )
		       + "'" ;
	}

	/**
	 * <ul>
	 * <li>设计作者：刘川</li>
	 * <li>设计日期：2009-8-10</li>
	 * <li>设计时间：下午05:46:27</li>
	 * <li>设计目的：</li>
	 * </ul>
	 * <ul>
	 * <b>修订历史</b>
	 * <li>1、</li>
	 * </ul>
	 * 
	 * @param object
	 * @return
	 */
	public static LibraManagedObject about (
	                                         Object object )
	{
		LibraManagedObject libraManagedObject =
		                                        AliasFactory
		                                                    .safeAbout ( object ) ;
		if ( libraManagedObject == null )
		{
			throw new IllegalStateException (
			                                  "对象：["
			                                          + object
			                                          + "]为空" ) ;
		}
		return libraManagedObject ;
	}

	/**
	 * <ul>
	 * <li>设计作者：刘川</li>
	 * <li>设计日期：2009-8-10</li>
	 * <li>设计时间：下午05:43:15</li>
	 * <li>设计目的：</li>
	 * </ul>
	 * <ul>
	 * <b>修订历史</b>
	 * <li>1、</li>
	 * </ul>
	 * 
	 * @param object
	 * @param infoLibraManagedObject
	 */
	public static void remember (
	                              Object object ,
	                              LibraManagedObject infoLibraManagedObject )
	{
		AliasFactory
		            .bindings ( )
		            .put (
		                   object ,
		                   infoLibraManagedObject ) ;
	}

	/**
	 * <ul>
	 * <li>设计作者：刘川</li>
	 * <li>设计日期：2009-8-10</li>
	 * <li>设计时间：下午05:43:20</li>
	 * <li>设计目的：</li>
	 * </ul>
	 * <ul>
	 * <b>修订历史</b>
	 * <li>1、</li>
	 * </ul>
	 * 
	 * @param object
	 * @param type
	 * @param alias
	 */
	public static void rememberAsAbstractSchemaName (
	                                                  Object object ,
	                                                  String type ,
	                                                  String alias )
	{
		AliasFactory
		            .bindings ( )
		            .put (
		                   object ,
		                   new AliasedAbstractSchemaName (
		                                                   type ,
		                                                   alias ) ) ;
	}

	/**
	 * <ul>
	 * <li>设计作者：刘川</li>
	 * <li>设计日期：2009-8-10</li>
	 * <li>设计时间：下午05:45:58</li>
	 * <li>设计目的：</li>
	 * </ul>
	 * <ul>
	 * <b>修订历史</b>
	 * <li>1、</li>
	 * </ul>
	 * 
	 * @param object
	 * @param path
	 * @param alias
	 */
	public static void rememberAsAliasedAssociationPath (
	                                                      Object object ,
	                                                      String path ,
	                                                      String alias )
	{
		AliasFactory
		            .bindings ( )
		            .put (
		                   object ,
		                   new AliasedAssociationPath (
		                                                path ,
		                                                alias ) ) ;
	}

	/**
	 * <ul>
	 * <li>设计作者：刘川</li>
	 * <li>设计日期：2009-8-10</li>
	 * <li>设计时间：下午05:45:50</li>
	 * <li>设计目的：</li>
	 * </ul>
	 * <ul>
	 * <b>修订历史</b>
	 * <li>1、</li>
	 * </ul>
	 * 
	 * @param object
	 * @param path
	 * @param alias
	 */
	public static void rememberAsAliasedInCollection (
	                                                   Object object ,
	                                                   String path ,
	                                                   String alias )
	{
		AliasFactory
		            .bindings ( )
		            .put (
		                   object ,
		                   new AliasedInCollection (
		                                             path ,
		                                             alias ) ) ;
	}

	/**
	 * <ul>
	 * <li>设计作者：刘川</li>
	 * <li>设计日期：2009-8-10</li>
	 * <li>设计时间：下午05:45:42</li>
	 * <li>设计目的：</li>
	 * </ul>
	 * <ul>
	 * <b>修订历史</b>
	 * <li>1、</li>
	 * </ul>
	 * 
	 * @param object
	 * @param path
	 */
	public static void rememberAsAssociationPath (
	                                               Object object ,
	                                               String path )
	{
		AliasFactory
		            .bindings ( )
		            .put (
		                   object ,
		                   new AssociationPath (
		                                         path ) ) ;
	}

	/**
	 * <ul>
	 * <li>设计作者：刘川</li>
	 * <li>设计日期：2009-8-10</li>
	 * <li>设计时间：下午05:45:17</li>
	 * <li>设计目的：</li>
	 * </ul>
	 * <ul>
	 * <b>修订历史</b>
	 * <li>1、</li>
	 * </ul>
	 * 
	 * @param <E>
	 * @param object
	 * @param path
	 * @param elementType
	 * @param elementProxy
	 */
	public static < E > void rememberAsCollectionAssociationPath (
	                                                               Object object ,
	                                                               String path ,
	                                                               Class < E > elementType ,
	                                                               E elementProxy )
	{
		AliasFactory
		            .bindings ( )
		            .put (
		                   object ,
		                   new CollectionAssociationPath < E > (
		                                                         path ,
		                                                         elementType ,
		                                                         elementProxy ) ) ;
	}

	/**
	 * <ul>
	 * <li>设计作者：刘川</li>
	 * <li>设计日期：2009-8-10</li>
	 * <li>设计时间：下午05:45:13</li>
	 * <li>设计目的：</li>
	 * </ul>
	 * <ul>
	 * <b>修订历史</b>
	 * <li>1、</li>
	 * </ul>
	 */
	public static void resetBindings ( )
	{
		AliasFactory.bindings
		                     .set ( new WeakIdentityHashMap < Object , LibraManagedObject > ( ) ) ;
	}

	/**
	 * <ul>
	 * <li>设计作者：刘川</li>
	 * <li>设计日期：2009-8-10</li>
	 * <li>设计时间：下午05:45:03</li>
	 * <li>设计目的：</li>
	 * </ul>
	 * <ul>
	 * <b>修订历史</b>
	 * <li>1、</li>
	 * </ul>
	 * 
	 * @param object
	 * @return
	 */
	public static LibraManagedObject safeAbout (
	                                             Object object )
	{
		return AliasFactory
		                   .bindings ( )
		                   .get (
		                          object ) ;
	}

	/**
	 * <ul>
	 * <li>设计作者：刘川</li>
	 * <li>设计日期：2009-8-10</li>
	 * <li>设计时间：下午02:52:34</li>
	 * <li>设计目的：</li>
	 * </ul>
	 * <ul>
	 * <b>修订历史</b>
	 * <li>1、</li>
	 * </ul>
	 * 
	 * @param object
	 * @return
	 */
	@ SuppressWarnings ( "unchecked" )
	public static String safeStringForm (
	                                      Object object )
	{
		if ( object instanceof LibraManagedObject )
		{
			LibraManagedObject libraManagedObject =
			                                        ( LibraManagedObject ) object ;
			return libraManagedObject
			                         .getPreferredStringRepresentation ( ) ;
		}
		LibraManagedObject aboutLibraManagedObject =
		                                             AliasFactory
		                                                         .safeAbout ( object ) ;
		if ( aboutLibraManagedObject == null )
		{
			if ( String.class
			                 .equals ( object
			                                 .getClass ( ) ) )
			{
				return AliasFactory
				                   .escape ( ( String ) object ) ;
			}
			else if ( Character.class
			                         .equals ( object
			                                         .getClass ( ) ) )
			{
				return AliasFactory
				                   .escape ( object
				                                   .toString ( ) ) ;
			}
			else if ( object instanceof ISubQuery )
			{
				return "("
				       + object
				               .toString ( )
				       + ")" ;
			}
			else if ( object instanceof Date )
			{
				throw new IllegalArgumentException (
				                                     "Illegal usage of a Date parameter. Note that there is "
				                                             + "no such thing as a Date literal in JPAQL, maybe "
				                                             + "what you were looking for is a query parameter ?" ) ;
			}
			else if ( object instanceof Enum )
			{
				return object
				             .getClass ( )
				             .getName ( )
				       + "."
				       + ( ( Enum ) object )
				                            .name ( ) ;
			}
			else
			{
				return object
				             .toString ( ) ;
			}
		}
		else
		{
			return aboutLibraManagedObject
			                              .getPreferredStringRepresentation ( ) ;
		}
	}
}
